package com.apobates.jforum2.troll.notices;

import com.apobates.jforum2.threads.stub.vo.ThreadsVo;
import com.apobates.jforum2.troll.forum.stub.vo.BoardVo;
import com.apobates.jforum2.troll.notices.biz.ForumLetterService;
import com.apobates.jforum2.troll.notices.biz.impl.api.LetterFeignServiceApi;
import com.apobates.jforum2.troll.notices.entity.ForumLetter;
import com.apobates.jforum2.troll.notices.entity.ForumLetterReceiver;
import com.apobates.jforum2.troll.regular.event.*;
import com.apobates.jforum2.troll.replies.stub.vo.ReplyVo;
import com.apobates.jforum2.troll.utils.core.Commons;
import com.apobates.jforum2.troll.utils.core.DateTimeUtils;
import com.google.gson.Gson;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;

@Configuration
public class RabbitMQEventLetterConfig {
    @Autowired
    private ForumLetterService forumLetterService;
    @Autowired
    private LetterFeignServiceApi letterFeignServiceApi;
    @Value("${site.appname}")
    private String siteNames;
    private final static Logger logger = LoggerFactory.getLogger(RabbitMQEventLetterConfig.class);

    //spring-cloud-stream事件消费者
    /*
    @Bean
    public Consumer<String> topicAction() {
        logger.error("[LTE]start consume topic event");
        return talBody -> {
            TopicActionLog tal = new Gson().fromJson(talBody, TopicActionLog.class);
            handleTopicAction(tal);
        };
    }

    @Bean
    Consumer<String> boardAction() {
        logger.error("[LTE]start consume board event");
        return balBody -> {
            BoardActionLog bal = new Gson().fromJson(balBody, BoardActionLog.class);
        }
    }*/

    @Bean
    Consumer<String> topicMoveAction(){
        logger.error("[LTE]start consume topic move event");
        return tmalBody -> {
            TopicMoveLog tmal = new Gson().fromJson(tmalBody, TopicMoveLog.class);
            handleTopicMoveAction(tmal);
        };
    }

    @Bean
    public Consumer<String> postsAction() {
        logger.error("[LTE]start consume posts event");
        return palBody -> {
            PostsActionLog pal = new Gson().fromJson(palBody, PostsActionLog.class);
            handlePostsAction(pal);
        };
    }

    @Bean
    public Consumer<String> memberAction() {
        logger.error("[LTE]start consume member event");
        return palBody -> {
            MemberActionLog mal = new Gson().fromJson(palBody, MemberActionLog.class);
            handleMemberAction(mal);
        };
    }

    //发送消息
    private void send(ForumLetter letter, Collection<ForumLetterReceiver> receiver){
        forumLetterService.create(letter, receiver);
    }

    //根据动作来处理消息
    private void handleMemberAction(MemberActionLog mal){
        switch (mal.getAction()){
            case MEMBER_REGISTER:
                handleMemberSignAction(mal);
                break;
            case MEMBER_LOGIN:
                handleMemberLoginAction(mal);
                break;
        }
    }

    private void handlePostsAction(PostsActionLog pal){
        switch (pal.getAction()){
            case POSTS_REPLY:
                handleComposePostsAction(pal);
                break;
            case POSTS_LIKED:
                handlePostsMoodAction(pal);
                break;
        }
    }

    private void handleMemberSignAction(MemberActionLog mal){
        logger.error("[LTE]hanler member registe action");
        ForumLetter helloNotic = getRegisterNotice(siteNames);
        send(helloNotic, List.of(new ForumLetterReceiver(mal.getMemberId(), mal.getMemberNickname())));
    }

    private void handleMemberLoginAction(MemberActionLog mal){
        logger.error("[LTE]hanler member login action");
        ForumLetter abnormalNotic = getLoginAbnormalNotic(mal.getMemberNickname(), mal.getIpAddr());
        send(abnormalNotic, List.of(new ForumLetterReceiver(mal.getMemberId(), mal.getMemberNickname())));
    }

    private void handlePostsMoodAction(PostsActionLog pal){
        logger.error("[LTE]hanler posts mood action");
        ThreadsVo topic = letterFeignServiceApi.getTopicById(pal.getTopicId()).getBody();
        ForumLetter moodNotice = getMoodNotice(pal.getMemberNickname(), pal.getLink());
        send(moodNotice, List.of(new ForumLetterReceiver(topic.getMember(), topic.getNickname())));
    }

    private void handleComposePostsAction(PostsActionLog pal){
        logger.error("[LTE]hanler posts reply action");
        //当前回复所属的话题
        ThreadsVo topic = letterFeignServiceApi.getTopicById(pal.getTopicId()).getBody();
        //当前回复
        ReplyVo posts = letterFeignServiceApi.getPostsById(pal.getPostsId()).getBody();
        ForumLetter replyNotice = getReplyNotice(topic, posts);
        logger.error("[LTE]hanler notice topic author");
        send(replyNotice, List.of(new ForumLetterReceiver(topic.getMember(), topic.getNickname())));
        //回复中是否能提取引用的cite
        long quotePostsId = parseBlockquoteTag(posts.getContent());
        if (quotePostsId <= 0) {
            logger.info("[Posts][PublishEvent][3]回复中无引用记录");
            return;
        }
        logger.info("[Posts][PublishEvent][3]引用的回复ID: " + quotePostsId);
        //当前回复中引用的回复
        ReplyVo quotePosts = letterFeignServiceApi.getPostsById(quotePostsId).getBody();
        if (null != quotePosts) {
            try {
                ForumLetter quoteNotice = getQuoteNotice(topic, quotePosts, posts.getFloor());
                send(quoteNotice, List.of(new ForumLetterReceiver(quotePosts.getMember(), quotePosts.getNickname())));
            } catch (Exception e) {}
        }
        logger.info("[Posts][PublishEvent][3]回复动作引用处理结束");
    }

    private void handleTopicMoveAction(TopicMoveLog tmal){
        logger.error("[LTE]hanler topic move action");
        BoardVo board = letterFeignServiceApi.getBoardById(tmal.getBoard()).getBody();
        ForumLetter fl = getTopicMoveNotice(tmal.getManagerNickname(), tmal.getTitle(), tmal.getLink(),board.getTitle());
        send(fl, List.of(new ForumLetterReceiver(tmal.getMemberId(), tmal.getMemberNickname())));
    }

    //-------------------------------------------------------------消息模板
    //提取blockquote属性的cite
    private long parseBlockquoteTag(String postsContent) {
        Document doc = Jsoup.parse(postsContent);
        Element quoteTag = doc.selectFirst("blockquote");
        if (null == quoteTag) {
            return -1L;
        }
        Element quoteAnchor = quoteTag.selectFirst("a");
        if (null == quoteAnchor) {
            return 0L;
        }
        try {
            String quoteAnchorHref = quoteAnchor.attr("href");
            return Long.valueOf(quoteAnchorHref.substring(quoteAnchorHref.lastIndexOf("#posts-") + 7));
        } catch (Exception e) {
            return -2L;
        }
    }
    //-------------------------------------------------------------消息模板
    //注册
    private ForumLetter getRegisterNotice(String siteNames) {
        String title = "欢迎您加入" + siteNames + "大家庭!";
        String content = "恭喜, 您已经完成了会员帐户注册, 请牢记您的登录信息. 在这里可以跟小伙伴们一起分享您的知识、您的快乐. 如果您发现任何问题, 请您及时向我们提出反馈或建议.";
        return ForumLetter.noticeLetter(title, content);
    }

    //登录时IP变更
    private ForumLetter getLoginAbnormalNotic(String names, String requestAddress) {
        LocalDateTime loginDateTime = LocalDateTime.now();
        return ForumLetter.noticeLetter(
                "异地登录通知",
                String.format("亲爱的:%s, 您的帐户于%s在%s完成了登录, 若非本人操作请注意您的帐户安全", names, DateTimeUtils.getRFC3339(loginDateTime), requestAddress));
    }

    //话题移动通知
    private ForumLetter getTopicMoveNotice(String operateNickname, String topicTitle, String targetLink, String targetBoardName){
        LocalDateTime operateDate = LocalDateTime.now();
        String content = String.format("%s在%s将话题: <a href=\"%s\">#%s#</a> , 移至%s版块, 如果存在异议您可以联系在线管理员",
                operateNickname,
                DateTimeUtils.getRFC3339(operateDate),
                targetLink,
                topicTitle,
                targetBoardName);
        ForumLetter flr = ForumLetter.noticeLetter("您发布的话题已经被管理员移至新版块", content);
        return flr;
    }

    //生成回复通知
    private ForumLetter getReplyNotice(ThreadsVo topic, ReplyVo posts) {
        //title: 张三回复了您的主题
        //content: {张三}: {回复内容} #{主题}#
        String floorLink = posts.getLink();
        String replyContent = Commons.htmlPurifier(posts.getContent());
        try {
            replyContent = replyContent.substring(0, 100) + "...";
        } catch (IndexOutOfBoundsException e) {}

        return ForumLetter.noticeLetter(
                posts.getNickname() + "回复了您的主题",
                String.format(
                        "<p><strong><a href=\"/member/%d.xhtml\">%s</a>: </strong>%s <a class=\"embed-link\" href=\"%s\">#%s#</a></p>", //<a href=\"/member/%d.xhtml\">%s</a>回复了您在<a href=\"/board/%d.xhtml\">%s</a>版块中发布的话题<a href=\"/topic/%d.xhtml\">#%s#</a>
                        posts.getMember(),
                        posts.getNickname(),
                        Commons.optional(replyContent, "查看内容"),
                        floorLink,
                        topic.getTitle()));
    }

    //生成引用通知
    private ForumLetter getQuoteNotice(ThreadsVo topic, ReplyVo posts, long authorReplyFloor) {
        String floorLink = posts.getLink();
        //String.format("%s#posts-%d", TopicReplica.produceLink.apply(topic.getId(), topic.getBoardId(), topic.getVolumesId()), posts.getId());
        return ForumLetter.noticeLetter(
                posts.getNickname() + "引用了您的回复",
                String.format(
                        "<p><a href=\"/member/%d.xhtml\">%s</a>引用了您在<a href=\"%s\">#%s#</a>%d楼发布的回复内容</p>",
                        posts.getMember(),
                        posts.getNickname(),
                        floorLink,
                        topic.getTitle(),
                        authorReplyFloor));
    }

    //回复喜好动作通知
    private ForumLetter getMoodNotice(String operator, String postsLink){
        LocalDateTime operateDate = LocalDateTime.now();
        String content = String.format("<p>%s在%s为您的回复点赞, <a class=\"embed-link\" href=\"%s\">查看回复</a></p>", operator, DateTimeUtils.getRFC3339(operateDate), postsLink);
        return ForumLetter.noticeLetter("您的回复收到一条点赞记录", content);
    }
}
